import copy
romeNumber = {1: 'i', 2: 'ii', 3: 'iii', 4: 'iv', 5: 'v', 6: 'vi', 7: 'vii',
              8: 'viii', 9: 'ix', 10: 'x', 11: 'xi', 12: 'xii', 13: 'xiii', 14: 'xiv'}
numRome = {'i': 1, 'ii': 2, 'iii': 3, 'iv': 4, 'v': 5, 'vi': 6, 'vii': 7,
           'viii': 8, 'ix': 9, 'x': 10, 'xi': 11, 'xii': 12, 'xiii': 13, 'xiv': 14}


class Pos:
    def __init__(self, bw: bool, x: int, y: int) -> None:
        self.bw = bw
        self.x = x
        self.y = y

    def __hash__(self):
        return hash((self.bw, self.x, self.y))

    def __repr__(self):
        return str((self.bw, self.x, self.y))

    def __eq__(self, value: "Pos"):
        return self.bw == value.bw and self.x == value.x and self.y == value.y

    def x_right_down(self):
        '''向右下沿着垂直棋盘边的方向移动一步'''
        if self.bw == 1:
            return self.right()
        else:
            return self.right().right().down()

    def x_right_up(self):
        '''向右上沿着垂直棋盘边的方向移动一步'''
        if self.bw == 1:
            return self.right().right().up()
        else:
            return self.right()

    def x_left_up(self):
        if self.bw == 1:
            return self.left().left().up()
        else:
            return self.left()

    def x_left_down(self):
        if self.bw == 1:
            return self.left()
        else:
            return self.left().left().down()

    def right_down(self):
        if self.bw == 1:
            return self.right()
        else:
            return self.down()

    def right_up(self):
        if self.bw == 1:
            return self.up()
        else:
            return self.right()

    def left_up(self):
        if self.bw == 1:
            return self.up()
        else:
            return self.left()

    def left_down(self):
        if self.bw == 1:
            return self.left()
        else:
            return self.down()

    def left(self):
        if self.bw == 1:
            return Pos(0, self.x, self.y)
        else:
            return Pos(1, self.x-1, self.y)

    def right(self):
        if self.bw == 1:
            return Pos(0, self.x+1, self.y)
        else:
            return Pos(1, self.x, self.y)

    def up(self):
        if self.bw == 1:
            return Pos(0, self.x, self.y+1)
        else:
            return Pos(1, self.x-1, self.y+1)

    def down(self):
        if self.bw == 1:
            return Pos(0, self.x+1, self.y-1)
        else:
            return Pos(1, self.x, self.y-1)

    def go(self, method="left", det=1):
        res = Pos(self.bw, self.x, self.y)
        for i in range(det):
            getattr(res, method)()
        return res

    def to_tuple(self):
        return (self.bw, self.x, self.y)

    def valid(self):
        if self.bw == 1:
            return 1 <= self.x and self.x <= 11 and 1 <= self.y and self.y <= 11
        else:
            return 1 <= self.x and self.x <= 12 and 1 <= self.y and self.y <= 12

    @staticmethod
    def checkValid(bw: int, x: int, y: int):
        return Pos(bw, x, y).valid()
    # TODO NAR Trans

    def toNAR(self):
        z = self.y+(self.x-1)+self.bw
        return str((12-self.y+1, chr(ord('a')+z-1), romeNumber[12-self.x+1]))

    def toNARTuple(self):
        z = self.y+(self.x-1)+self.bw
        return (12-self.y+1, chr(ord('a')+z-1), romeNumber[12-self.x+1])

    @staticmethod
    def fromNAR(h, r, l):
        x = 12-numRome[l]+1
        y = 12-h+1
        r = ord(r)-ord('a')+1
        return Pos(r-(x-1)-y, x, y)


'''
执行策略集
'''


class PosSet:
    def __init__(self, ps: "list[Pos]" = []) -> None:
        self.pos = set(ps)

    def exists(self, x: Pos):
        for i in self.pos:
            if i.to_tuple() == x.to_tuple():
                return True
        return False

    def intersection(self, x):
        return self.pos & set(x)

    def differ(self, x):
        return self.pos-set(x)

    def union(self, x):
        return self.pos | set(x)

    def update(self, x):
        self.pos = self.pos & set(x)

    def remove(self, x):
        self.pos = self.pos-set(x)

    def add(self, x: "Pos") -> bool:
        if x.valid() == False:
            return False
        self.pos.add(x)
        return True
